package concurrents.pool;

import java.util.LinkedList;

/**
 * Created by Glogo on 2014/9/1.
 *
 * 它有两个主要的功能：
 *    一 是获取线程组中处于活跃状态线程的列表；
 *    二 是设置为线程设置未捕获异常处理器(ncaught exception handler)。
 *
 * 在Java 1.5中Thread类也添加了setUncaughtExceptionHandler(UncaughtExceptionHandler eh) 方法
 * 所以ThreadGroup是已经过时的，不建议继续使用。
 */
public class MyThreadPoolDemo extends ThreadGroup {

    private boolean isClosed = false;
    private LinkedList<Runnable> workQueue;
    private static int threadPoolID;
    private int threadID;

    public MyThreadPoolDemo(int poolSize){
        super("ThreadPool-" + (threadPoolID++));
        setDaemon(true);
        workQueue = new LinkedList<>();
        for(int i = 0; i < poolSize; i++){
            new WorkerThread().start();
        }
    }

    /**
     * 向任务队列中加入一个新任务，由工作线程去执行该任务
     * @param task
     */
    public synchronized void execute(Runnable task){
        if(isClosed){
            throw new IllegalStateException();
        }
        if(task != null){
            workQueue.add(task);
            notify();
        }
    }

    public synchronized void close() {
        if(!isClosed){
            isClosed = true;
            workQueue.clear();
            interrupt();
        }
    }

    /**
     * 等待工作线程完成所有任务
     */
    public void join() {
        synchronized (this){
            isClosed = true;
            notifyAll();
        }
        Thread[] threads = new Thread[activeCount()];
        int count = enumerate(threads); //获得线程组中所有活着的线程
        for (int i = 0; i < count; i++){
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 从任务队列中取出一个任务，工作线程会调用此方法
     * @return
     * @throws InterruptedException
     */
    protected synchronized Runnable getTask() throws InterruptedException {
        while (workQueue.size() == 0){
            if(isClosed)    return null;
            wait();
        }
        return workQueue.removeFirst();
    }

    private static Runnable createTask(final int taskId){
        return new Runnable() {
            @Override
            public void run() {
                System.out.println("Task " + taskId + ":start");
                try{
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskId + ":end");
            }
        };
    }

    public static void main(String[] args){
        int numTasks = Integer.parseInt(args[0]);
        int poolSize = Integer.parseInt(args[1]);

        MyThreadPoolDemo threadPool = new MyThreadPoolDemo(poolSize);
        for (int i = 0; i < numTasks; i++){
            threadPool.execute(createTask(i));
        }
        threadPool.join();
    }


    /**
     * 工作线程类
     */
    private class WorkerThread extends Thread {

        public WorkerThread(){
            super(MyThreadPoolDemo.this, "WorkerThread-" + (threadID++));
        }

        @Override
        public void run() {
            while(!isInterrupted()){
                Runnable task = null;
                try{
                    task = getTask();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(task == null)    return;
                try{
                    task.run();
                }catch (Throwable t){
                    t.printStackTrace();
                }
            }
        }
    }



}
